﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace AyuBookmark.Common.Input
{
    /// <summary>
    /// 全局键盘和鼠标输入监听器
    /// </summary>
    public class InputListener : IDisposable
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WH_MOUSE_LL = 14;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_LBUTTONDOWN = 0x0201;

        private delegate IntPtr LowLevelProc(int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("user32.dll")]
        private static extern short GetKeyState(int nVirtKey);

        private IntPtr _keyboardHookId = IntPtr.Zero;
        private IntPtr _mouseHookId = IntPtr.Zero;
        private readonly IKeyboardMouseEvents _eventHandler;
        private bool _disposed;

        /// <summary>
        /// 初始化输入监听器
        /// </summary>
        /// <param name="eventHandler">事件处理器</param>
        public InputListener(IKeyboardMouseEvents eventHandler)
        {
            _eventHandler = eventHandler ?? throw new ArgumentNullException(nameof(eventHandler));
            SetHooks();
        }

        /// <summary>
        /// 设置键盘和鼠标钩子
        /// </summary>
        private void SetHooks()
        {
            using (var curProcess = Process.GetCurrentProcess())
            using (var curModule = curProcess.MainModule)
            {
                _keyboardHookId = SetHook(WH_KEYBOARD_LL, KeyboardHookProc);
                _mouseHookId = SetHook(WH_MOUSE_LL, MouseHookProc);
            }
        }

        private IntPtr SetHook(int hookType, LowLevelProc proc)
        {
            using (var curProcess = Process.GetCurrentProcess())
            using (var curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(hookType, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                _eventHandler.OnKeyPressed((VirtualKeyCode)vkCode);
            }
            return CallNextHookEx(_keyboardHookId, nCode, wParam, lParam);
        }

        private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_LBUTTONDOWN)
            {
                _eventHandler.OnMouseClicked(MouseButton.Left);
            }
            return CallNextHookEx(_mouseHookId, nCode, wParam, lParam);
        }

        /// <summary>
        /// 检查指定按键是否按下
        /// </summary>
        public static bool IsKeyPressed(VirtualKeyCode keyCode)
        {
            return (GetKeyState((int)keyCode) & 0x8000) != 0;
        }

        /// <summary>
        /// 释放钩子资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                if (_keyboardHookId != IntPtr.Zero)
                {
                    UnhookWindowsHookEx(_keyboardHookId);
                    _keyboardHookId = IntPtr.Zero;
                }

                if (_mouseHookId != IntPtr.Zero)
                {
                    UnhookWindowsHookEx(_mouseHookId);
                    _mouseHookId = IntPtr.Zero;
                }
            }
            _disposed = true;
        }

        ~InputListener()
        {
            Dispose(false);
        }
    }

    /// <summary>
    /// 键盘鼠标事件处理器接口
    /// </summary>
    public interface IKeyboardMouseEvents
    {
        /// <summary>
        /// 当键盘按键按下时触发
        /// </summary>
        void OnKeyPressed(VirtualKeyCode key);

        /// <summary>
        /// 当鼠标按钮点击时触发
        /// </summary>
        void OnMouseClicked(MouseButton button);
    }

    /// <summary>
    /// 虚拟键码枚举
    /// </summary>
    public enum VirtualKeyCode
    {
        LeftButton = 0x01,
        RightButton = 0x02,
        Cancel = 0x03,
        MiddleButton = 0x04,
        // 其他键码...
        A = 0x41,
        B = 0x42,
        // 更多键码...
        LeftWindows = 0x5B,
        RightWindows = 0x5C,
        // 完整列表可参考Windows API文档
    }

    /// <summary>
    /// 鼠标按钮枚举
    /// </summary>
    public enum MouseButton
    {
        Left,
        Right,
        Middle,
        XButton1,
        XButton2
    }
}